using System;
using System.Collections.Generic;
using System.Configuration;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;

namespace Comteck.Winforms.Utils {
  /// <summary>
  /// ConfigurationManager帮助类
  /// </summary>
  public class ConfigManagerHelper : BaseLog {
    /// <summary>
    /// 获取指定值
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="parseFunc"></param>
    /// <param name="defaultTValueFunc"></param>
    /// <param name="key"></param>
    /// <param name="supressKey"></param>
    /// <returns></returns>
    public static T GetValue<T>(Func<string, T> parseFunc, Func<T> defaultTValueFunc,
     [CallerMemberName]string key = "", string supressKey = "") {
      try {
        if (!supressKey.IsNullOrEmpty()) {
          key = supressKey;
        }

        string node;

        // 优先加载用户自定义配置
        var config = ConfigurationManager.OpenMappedExeConfiguration(new ExeConfigurationFileMap {
          ExeConfigFilename = Path.Combine(System.Windows.Forms.Application.StartupPath, "user.config"),
        }, ConfigurationUserLevel.None);
        if (config.AppSettings.Settings[key] != null && !string.IsNullOrWhiteSpace(config.AppSettings.Settings[key].Value)) {
          node = config.AppSettings.Settings[key].Value;
        } else {
          // 如果用户自定义配置不存在或为空，则加载系统默认配置
          node = ConfigurationManager.AppSettings[key];
        }

        return !string.IsNullOrWhiteSpace(node) ? parseFunc(node) :
          (defaultTValueFunc == null ? default(T) : defaultTValueFunc());
      } catch (Exception ex) {
        Logger.Error(string.Format("Error Reading app.config or web.config on node: {0}", key), ex);
        return default(T);
      }
    }

    /// <summary>
    /// 将app.config中的appsettings内容转换成模型
    /// </summary>
    /// <typeparam name="TResult"></typeparam>
    /// <returns></returns>
    public static TResult LoadAll<TResult>() where TResult : class {
      var model = Activator.CreateInstance<TResult>();

      // 取得Model中所有的属性
      var propertys = model.GetType().GetProperties(BindingFlags.GetProperty
        | BindingFlags.Public | BindingFlags.Instance);

      // 循环赋值
      foreach (var pi in propertys) {
        var value = GetValue(pi);

        // 设置属性值
        pi.SetValue(model, value, null);
      }

      return model;
    }

    /// <summary>
    /// 
    /// </summary>
    /// <param name="property"></param>
    /// <returns></returns>
    private static dynamic GetValue(PropertyInfo property) {
      dynamic value = null;

      switch (property.PropertyType.Name) {
        case nameof(String):
          value = GetValue(_ => _, null, property.Name);
          break;
        case nameof(Boolean):
          value = GetValue(bool.Parse, null, property.Name);
          break;
        case nameof(Decimal):
          value = GetValue(decimal.Parse, null, property.Name);
          break;
        case nameof(DateTime):
          value = GetValue(DateTime.Parse, null, property.Name);
          break;
        case nameof(Int32):
          value = GetValue(int.Parse, null, property.Name);
          break;
        case nameof(Int64):
          value = GetValue(long.Parse, null, property.Name);
          break;
        case nameof(TimeSpan):
        case nameof(Nullable<TimeSpan>):
          value = GetValue(TimeSpan.Parse, null, property.Name);
          break;
        default:
          value = GetValue(_ => _, null, property.Name);
          break;
      }

      return value;
    }

    public static void Save(IDictionary<string, string> keyValues)  {
      // 当前app.config
      var config = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);

      foreach (var key in keyValues.Keys) {
        AddOrUpdate(config, key, keyValues[key]);
      }

      // 保存
      config.Save(ConfigurationSaveMode.Full);
      //ConfigurationManager.RefreshSection(nameof(config.AppSettings).ToLower());
      ConfigurationManager.RefreshSection("appSettings");
    }

    /// <summary>
    /// 保存用户配置文件
    /// </summary>
    /// <param name="keyValues"></param>
    public static void SaveUserConfig(IDictionary<string, string> keyValues) {
      ExeConfigurationFileMap configFileMap = new ExeConfigurationFileMap() {
        ExeConfigFilename = Path.Combine(System.Windows.Forms.Application.StartupPath, "user.config"),
      };
      var config = ConfigurationManager.OpenMappedExeConfiguration(configFileMap, ConfigurationUserLevel.None);

      foreach (var key in keyValues.Keys) {
        AddOrUpdate(config, key, keyValues[key]);
      }

      config.Save(ConfigurationSaveMode.Full);
      ConfigurationManager.RefreshSection("appSettings");
    }

    /// <summary>
    /// 增加或者修改config的值
    /// </summary>
    /// <param name="config"></param>
    /// <param name="key"></param>
    /// <param name="value"></param>
    public static void AddOrUpdate(System.Configuration.Configuration config, string key, string value) {
      if (config.AppSettings.Settings.AllKeys.Any(x => key.Equals(x, StringComparison.OrdinalIgnoreCase))) {
        config.AppSettings.Settings[key].Value = value;
      } else {
        config.AppSettings.Settings.Add(key, value);
      }
    }

  }
}
